home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 6
/
QRZ Ham Radio Callsign Database - Volume 6.iso
/
mac
/
files
/
packet
/
ax25ip.shr
< prev
next >
Wrap
Text File
|
1992-01-23
|
46KB
|
1,831 lines
[ This device driver for the SunOS kernel allows the kernel network
layer to send IP packet inside AX25 (using a TNC on a serial port),
exactly like KA9Q NOS does.
The AX25 device appears exactly (ok, minus possible bugs :-) like
any other network device does to the kernel, so you can use any old
regular SunOS TCP/IP programs (ftp, telnet, etc). (Tested on Sun3/60
and Sun4/260, SunOS4.1.1.)
VERSION 1.0 deraadt@lego.cuc.ab.ca ]
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: Makefile README ax25.8 ax25.c ax25ether.c if_ax.h tty_ax.c
# Wrapped by deraadt@cpsc.UCalgary.CA on Sat Jan 25 02:48:06 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(73 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS= -g
XBIN= ax25ether ax25
X
Xall: $(BIN)
X
Xclean:
X $(RM) *.o *~ $(BIN)
END_OF_FILE
if test 73 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3792 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XSTATUS:
XTested on a Sun3/60 and a Sun4/260 running SunOS4.1.1, using a PacComm
XTiny-2 TNC, and talking with other NOS sites in Calgary, Alberta.
X
XINSTALL:
X0. Substitute the name 'KERNEL_CONFIG_FILE' in the following steps with the
X kernel configuration file for your new kernel (If in doubt, make a copy
X of GENERIC, and use it).
X Also, substitute 'sun3' with whatever the command 'arch -k' says
X your kernel architecture is.
X
X1. First, you need to add the device driver to the kernel. Add this line to
X /usr/sys/sun3/conf/KERNEL_CONFIG_FILE.
X pseudo-device ax1 init ax_attach
X ^ this number determines how many TNCs you can hook up.
X
X2. splice these sections in the appropriate (fairly obvious) places in
X /usr/sys/sun/str_conf.c
X #include "ax.h"
X
X #if NAX > 0
X extern struct streamtab axinfo;
X #endif
X
X #if NAX > 0
X { "ax25", &axinfo },
X #endif
X
X3. add this line to /usr/sys/conf.common/files.cmn
X os/tty_ax.c optional ax
X
X4. Install the needed files in the kernel sys tree
X # cp tty_ax.c /usr/sys/os
X # cp if_ax.h /usr/include/sys
X # cp if_ax.h /usr/sys/sys
X
X5. Build the kernel
X # cd /usr/sys/sun3/conf
X # config KERNEL_CONFIG_FILE
X # cd ../KERNEL_CONFIG_FILE
X # make
X # mv /vmunix /vmunix.save
X # cp vmunix /vmunix
X
X6. Reboot your machine to start up the new kernel.
X
X7. Now, build the two user level programs: ax25ether and ax25, and give
X it a try.
X # make
X
X8. Put your hostname in /etc/hosts with the correct IP address.
X 44.135.145.28 ve6uug-0
X
X9. Ensure that the netmask for network #44 is correct. Ussually it should
X be 0xffffff00. Put that in /etc/netmasks, like this.
X 44 255.255.255.0
X (If you are running YP, you may need to rebuild the databases.
X # (cd /var/yp; make)
X )
X
X10. Ensure your TNC is in KISS mode, with the proper KISS timing parameters
X already set. Now we can start up the interface.
X
X # ./ax25 -v ve6uug-0 ve6uug-0 /dev/ttyb
X popping module: ttcompat
X popping module: ldterm
X pushing module: ax25
X network device: ax0
X addresses: ax25 ac.8a.6c.aa.aa.8e.60 'VE6UUG-0' = ether 99:da:55:b5:d6:70
X execute: ifconfig ax0 ve6uug-0 netmask + broadcast + up
X Setting netmask of ax0 to 255.255.255.0
X
X The first instance of your callsign is resolved according to /etc/hosts
X to generate an IP address. The second instance of your callsign determines
X what your AX25 hardware address is, which is what other parties use to
X actually send a packet to your hardware.
X
X11. Check to see if the interface has come up.
X # netstat -in
X Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue
X le0 1500 136.159.222.0 136.159.222.1 3871 0 1847 0 0 0
X lo0 1536 127.0.0.0 127.0.0.1 339 0 339 0 0 0
X ax0 1000 44.135.145.0 44.135.145.28 0 0 0 0 0 0
X
X12. Try to talk to a few other hosts, ie. telnet, finger, etc.
X
XBUGS:
XGenerally, etherfind seems to work, but only on the second and successive
Xattempts. The first attempt fails with an NIOCBIND error. No idea why.
X
XPackets with digipeater addresses in their header are dropped on the floor
Ximmediately. Proper digipeater support cannot be easily added. (My opinion:
Xdigipeating is a dumb idea).
X
XDTR behaviour: M_HANGUP and M_UNHANGUP streams messages are not handled
Xcorrectly. Currently, it's best to <snip> your TNC's DTR line.
X
XOTHER NOTES:
XThe kernel ARP routines can only deal with 6 byte ethernet addresses. A
Xbizzare encoding scheme is used to encode AX25 7-byte addresses into these
X6-byte addresses. When AX25 addresses are converted, the resulting ethernet
Xaddresses always have their upper byte set to 0x99. The program ax25ether
Xwill convert between AX25 addresses and ethernet addresses as shown using
Xthe arp command.
END_OF_FILE
if test 3792 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'ax25.8' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ax25.8'\"
else
echo shar: Extracting \"'ax25.8'\" \(3814 characters\)
sed "s/^X//" >'ax25.8' <<'END_OF_FILE'
X.\" manual page v0.1 for ax25 pl-0
X.\" SH section heading
X.\" SS subsection heading
X.\" LP paragraph
X.\" IP indented paragraph
X.\" TP hanging label
X.TH AX25 8
X.SH NAME
Xax25 \- AX25/IP ifconfig Utility
X.SH SYNOPSIS
X.B ax25
X[
X.I \-v
X]
X.I <network address>
X.I <ham call sign>
X.I <tty_name>
X.SH DESCRIPTION
X.LP
XAmateur packet radio enthusiasts nowadays send IP packets over radio
Xlinks. Hanging off a serial port on their computer, TNC modems are
Xused to provide CSMA-like behaviour so that the single radio channel
Xcan be shared between multiple stations (somewhat like how ethernet
Xworks). Packet radio is a broadcast medium, hence the TNC is
Xresponsible for sharing the bandwidth with other TNC's. The computer
Xtalking to the TNC must use a protocol called KISS (a simple
Xderivative of SLIP encoding) to send/receive packets to/from the TNC.
X.LP
XAX25 packets vary in length. The packet header at the start of the
Xpacket has four parts:
X.TP
X1.
XA (guaranteed to be) unique source address.
X.TP
X2.
XA destination addresses.
X.TP
X3.
XAn AX25 packet type field. In our case it is always set to
XUI, to indicate that this is an AX25 datagram.
X.TP
X4.
XA small number, choosing between various higher level
Xprotocols, called the protocol ID.
X.LP
XThe addresses found in the header are a simple 7-byte encoding of the
XHAM radio call sign and substation ID. These addresses are used just
Xlike ethernet hardware addresses are, to provide a unique name for
Xeach station. The protocol ID can choose between many protocols but
Xusers of IP-over-AX25 under Unix are really only concerned with two
XAX25 sub-protocols: ARP and IP.
X.LP
XAX25 packets (received via KISS encoding from the TNC) which are found
Xto contain ARP or IP datagrams are decoded and handed off to the
Xkernel networking code. Similarily, the network code gives outbound
Xdatagrams to the AX25 device driver, where the reverse process occurs:
Xthey are encapsulated in AX25 packets and, after KISS encoding, sent
Xoff to the TNC for transmission.
X.LP
XBoth incoming and outgoing ARP datagrams require special handling.
XThe Unix kernel's internal ARP cache contains translations between
X4-byte IP addresses and 6-byte ethernet addresses. It's convenient to
Xnot rewrite the kernel's ARP implementation, so an encoding scheme was
Xdeveloped which converts 7-byte AX25 addresses to/from 6-byte ethernet
Xaddresses. This is too twisted to describe here, so refer to the
Xdevice driver source.
X.LP
X.SH OPTIONS
XYou must be root to run this. It's a good idea to start it from
X/etc/rc.local in the background.
X.TP
X.B \-v
XPrint out more information while setting up the link.
X.TP
X.B <network address>
XThis provides the IP address for the network port. This name gets passed
Xto ifconfig(8), so it can be a name out of the hosts(5) database.
X.TP
X.B <ham call sign>
XThis is your HAM call sign, with your substation ID.
X.TP
X.B <tty_name>
XCommunicate over the named device at 9600 baud.
X.LP
X.SH EXAMPLE
X.IP
Xax25 44.135.145.28 ve6uug-0 /dev/ttyb
X\".SH FILES
X.SH SEE ALSO
XMike Chepponis (K3MC), Phil Karn (KA9Q).
X.I The KISS TNC: A simple Host\-to\-TNC communications protocol.
X.LP
XPacComm.
X.I Operating Manual for PacComm Packet Controllers, pg. 31.
X.TP
X.B RFC1055
XRomkey, J.
X.I A Nonstandard for Transmission of IP Datagrams Over Serial Lines: SLIP
X.LP
XThe README file supplied with this AX25 package.
X.LP
X\".SH DIAGNOSTICS
X\".SH NOTES
X.SH BUGS
XEtherfind doesn't work as expected the first time you run it!
X.LP
XTNC's that toggle DTR for each packet can cause problems because
Xstreams M_HANGUP and M_UNHANGUP messages are treated incorrectly. If
Xyou see console messages about M_HANGUP and M_UNHANGUP, cutting the
XDTR line will solve the problem.
X.LP
X.SH AUTHORS
XTheo de Raadt \<deraadt\@lego.cuc.ab.ca\> [kernel hack]
X.LP
XWilliam Graham (VE6UUG) \<uug\@indigo.cuc.ab.ca\> [HAM]
X.LP
END_OF_FILE
if test 3814 -ne `wc -c <'ax25.8'`; then
echo shar: \"'ax25.8'\" unpacked with wrong size!
fi
# end of 'ax25.8'
fi
if test -f 'ax25.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ax25.c'\"
else
echo shar: Extracting \"'ax25.c'\" \(3577 characters\)
sed "s/^X//" >'ax25.c' <<'END_OF_FILE'
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <sys/stropts.h>
X#include <sys/termios.h>
X#include <sys/ttold.h>
X#include <sys/sockio.h>
X#include <sys/file.h>
X#include <sys/if_ax.h>
X#include <netinet/in.h>
X#include <net/if.h>
X#include <netinet/if_ether.h>
X#include <stdio.h>
X
Xu_char ax25broadcastaddr[7] = {
X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1
X};
Xstatic struct ether_addr etherbroadcastaddr = {
X 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
X};
X
Xint
Xmain(argc, argv)
Xchar **argv;
X{
X struct termios tios;
X u_char ax25[7];
X struct ether_addr eth;
X char cmd[128], name[64];
X u_char *cp, c;
X int verbose = 0;
X int unit = 777;
X int fd, i;
X
X if(argc<4) {
X printf("usage: %s [-v] inet-addr ham-call-sign tty\n", *argv);
X exit(0);
X }
X
X if( !strcmp(argv[1], "-v") ) {
X verbose = 1;
X argv++;
X }
X
X fd = open(argv[3], O_RDWR);
X if(fd == -1) {
X perror("open");
X exit(1);
X }
X
X while(1) {
X if(verbose)
X if(ioctl(fd, I_LOOK, name) != -1)
X printf("popping module: %s\n", name);
X if(ioctl(fd, I_POP, 0) == -1)
X break;
X }
X
X if( ioctl(fd, TCGETS, &tios) <0) {
X perror("ioctl TCGETS");
X exit(1);
X }
X
X tios.c_cflag = CRTSCTS | B9600;
X tios.c_cflag |= CS8|CREAD|HUPCL;
X tios.c_iflag = IGNBRK;
X if( ioctl(fd, TCSETS, &tios) <0) {
X perror("ioctl TCSETS");
X exit(1);
X }
X
X if(verbose)
X printf("pushing module: ax25\n");
X if( ioctl(fd, I_PUSH, "ax25") == -1) {
X perror("ioctl I_PUSH");
X exit(1);
X }
X
X if( ioctl(fd, AXIOGUNIT, &unit) != -1) {
X if(verbose)
X printf("network device: ax%d\n", unit);
X } else {
X perror("ioctl AXIOGUNIT");
X exit(1);
X }
X
X /*
X * convert the HAM call sign to an ax25_addr
X */
X i = 0;
X bzero((caddr_t)ax25, sizeof(ax25));
X for(cp=(u_char *)argv[2]; *cp && (i<6); cp++) {
X if(*cp=='-') {
X cp++;
X break;
X }
X c = islower(*cp) ? toupper(*cp) : *cp;
X ax25[i++] = (u_char)(c << 1);
X }
X while(i<6)
X ax25[i++] = (u_char)(' ' << 1);
X while(*cp=='-')
X cp++;
X if(*cp)
X ax25[6] = (u_char)(*cp << 1);
X
X ax_ax2ether(ax25, ð);
X if( ioctl(fd, AXIOSHADDR, ð) == -1) {
X perror("ioctl AXIOSHADDR");
X exit(1);
X }
X
X sprintf(cmd, "ifconfig ax%d %s netmask + broadcast + up",
X unit, argv[1]);
X if(verbose)
X printf("execute: %s\n", cmd);
X system(cmd);
X
X while(sigpause(0)!=-1)
X ;
X return 0;
X}
X
X
X/*
X * convert an ax25 address to an ether_addr
X */
Xax_ax2ether(axhp, ethp)
Xu_char *axhp;
Xstruct ether_addr *ethp;
X{
X u_char c;
X int i;
X
X printf("addresses: ax25 ");
X for(i=0; i<6; i++)
X printf("%02x.", axhp[i]);
X printf("%02x '", axhp[6]);
X
X for(i=0; i<(7-1); i++)
X printf("%c", axhp[i]>>1);
X printf("-%c' = ether ", axhp[6]>>1);
X
X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr,
X sizeof(ax25broadcastaddr)) ) {
X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp,
X sizeof(struct ether_addr));
X goto done;
X }
X
X ethp->ether_addr_octet[0] = 0x99;
X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[1] = c;
X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0);
X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f);
X ethp->ether_addr_octet[2] = c;
X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0);
X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f);
X ethp->ether_addr_octet[3] = c;
X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[4] = c;
X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0);
X c |= ((((axhp[6]>>1) - '0') ) & 0x0f);
X ethp->ether_addr_octet[5] = c;
X
Xdone:
X for(i=0; i<sizeof(struct ether_addr)-1; i++)
X printf("%02x:", ethp->ether_addr_octet[i]);
X printf("%02x\n", ethp->ether_addr_octet[5]);
X return 0;
X}
X
END_OF_FILE
if test 3577 -ne `wc -c <'ax25.c'`; then
echo shar: \"'ax25.c'\" unpacked with wrong size!
fi
# end of 'ax25.c'
fi
if test -f 'ax25ether.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ax25ether.c'\"
else
echo shar: Extracting \"'ax25ether.c'\" \(4192 characters\)
sed "s/^X//" >'ax25ether.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <net/if.h>
X#include <netinet/if_ether.h>
X#include <sys/if_ax.h>
X
Xu_char ax25broadcastaddr[7] = {
X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1
X};
Xstatic struct ether_addr etherbroadcastaddr = {
X 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
X};
Xstatic struct ether_addr ethernulladdr;
X
X/*
X * convert an ax25 address to an ether_addr
X */
Xax_ax2ether(axhp, ethp)
Xu_char *axhp;
Xstruct ether_addr *ethp;
X{
X u_char c;
X int i;
X
X for(i=0; i<6; i++)
X printf("%02x.", axhp[i]);
X printf("%02x '", axhp[6]);
X
X for(i=0; i<(7-1); i++)
X printf("%c", axhp[i]>>1);
X printf("-%c' == ", axhp[6]>>1);
X
X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr,
X sizeof(ax25broadcastaddr)) ) {
X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp,
X sizeof(struct ether_addr));
X goto done;
X }
X
X ethp->ether_addr_octet[0] = 0x99;
X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[1] = c;
X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0);
X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f);
X ethp->ether_addr_octet[2] = c;
X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0);
X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f);
X ethp->ether_addr_octet[3] = c;
X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[4] = c;
X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0);
X c |= ((((axhp[6]>>1) - '0') ) & 0x0f);
X ethp->ether_addr_octet[5] = c;
X
Xdone:
X for(i=0; i<sizeof(struct ether_addr)-1; i++)
X printf("%02x:", ethp->ether_addr_octet[i]);
X printf("%02x\n", ethp->ether_addr_octet[5]);
X return 0;
X}
X
X/*
X * convert an ether_addr to an ax25 address
X */
Xax_ether2ax(ethp, axhp)
Xstruct ether_addr *ethp;
Xu_char *axhp;
X{
X u_char c;
X int i;
X
X for(i=0; i<sizeof(struct ether_addr)-1; i++)
X printf("%02x:", ethp->ether_addr_octet[i]);
X printf("%02x == ", ethp->ether_addr_octet[5]);
X
X if( !bcmp((caddr_t)ethp, (caddr_t)ðernulladdr,
X sizeof(struct ether_addr))) {
X printf("nothing\n");
X return;
X }
X if( !bcmp((caddr_t)ethp, (caddr_t)ðerbroadcastaddr,
X sizeof(struct ether_addr))) {
X axhp[0] = 'Q' << 1;
X axhp[1] = 'S' << 1;
X axhp[2] = 'T' << 1;
X axhp[3] = ' ' << 1;
X axhp[4] = ' ' << 1;
X axhp[5] = ' ' << 1;
X axhp[6] = '0' << 1;
X goto done;
X }
X
X c = ethp->ether_addr_octet[0];
X if(c != 0x99) {
X printf("[NO MAPPING]\n");
X for(i=0; i<7; i++)
X axhp[i] = (i+1) << 1;
X return;
X }
X c = (ethp->ether_addr_octet[1] >> 2) & 0x3f;
X axhp[0] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[1] << 4) & 0x30;
X c |= (ethp->ether_addr_octet[2] >> 4) & 0x0f;
X axhp[1] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[2] << 2) & 0x3c;
X c |= (ethp->ether_addr_octet[3] >> 6) & 0x03;
X axhp[2] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[3] ) & 0x3f;
X axhp[3] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[4] >> 2) & 0x3f;
X axhp[4] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[4] << 4) & 0x30;
X c |= (ethp->ether_addr_octet[5] >> 4) & 0x0f;
X axhp[5] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[5] ) & 0x0f;
X axhp[6] = (u_char)((c + '0') << 1);
X
Xdone:
X for(i=0; i<6; i++)
X printf("%02x.", axhp[i]);
X printf("%02x '", axhp[6]);
X
X for(i=0; i<6; i++)
X printf("%c", (axhp[i]>>1) & 0x7f );
X printf("-%c'\n", (axhp[6]>>1) & 0x7f );
X}
X
Xmain(argc, argv)
Xchar **argv;
X{
X u_char ax25[7];
X struct ether_addr eth;
X u_char *cp, c;
X int i;
X
X if(argc<3) {
X fprintf(stderr, "usage: %s af addr\n", argv[0]);
X fprintf(stderr, "\taf=ax25, ether\n");
X exit(0);
X }
X
X if( !strcmp(argv[1], "ax25")) {
X i = 0;
X bzero((caddr_t)ax25, sizeof(ax25));
X for(cp=(u_char *)argv[2]; *cp && (i<6); cp++) {
X if(*cp=='-') {
X cp++;
X break;
X }
X c = islower(*cp) ? toupper(*cp) : *cp;
X ax25[i++] = (u_char)(c << 1);
X }
X while(i<6)
X ax25[i++] = (u_char)(' ' << 1);
X while(*cp=='-')
X cp++;
X if(*cp)
X ax25[6] = (u_char)(*cp << 1);
X ax_ax2ether(ax25, ð);
X
X } else if( !strcmp(argv[1], "ether")) {
X bcopy((caddr_t)ether_aton(argv[2]), (caddr_t)ð,
X sizeof(struct ether_addr));
X ax_ether2ax(ð, ax25);
X } else
X printf("what?\n");
X return 0;
X}
END_OF_FILE
if test 4192 -ne `wc -c <'ax25ether.c'`; then
echo shar: \"'ax25ether.c'\" unpacked with wrong size!
fi
# end of 'ax25ether.c'
fi
if test -f 'if_ax.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'if_ax.h'\"
else
echo shar: Extracting \"'if_ax.h'\" \(1890 characters\)
sed "s/^X//" >'if_ax.h' <<'END_OF_FILE'
X#ifndef _if_ax_h_
X#define _if_ax_h_
X
X#define AXIOGUNIT _IOR(x, 111, int) /* get unit number */
X#define AXIOSHADDR _IOW(x, 112, struct ether_addr) /* set ether_addr */
X
X#define AXSTREAMNAME "ax25" /* streams module name */
X#define AXIFNAME "ax" /* interface name */
X#define AX25MTU 1000 /* max ax25 packet size */
X
X/* An ax25 address is encoded as a struct ether_addr so that it can fit
X * in the arp tables.
X *
X * encoding format in struct ether_addr
X * ________ ______ ______ ______ ______ ______ ______ _____
X * | 8 | 6 | 6 | 6 | 6 | 6 | 6 | 4 |
X * |________|______|______|______|______|______|______|_____|
X *
X * The upper byte of ether_addr is set to 0x99.
X *
X * The next 6 6-bit fields are each filled with an ax25_addr.aa_c[] entry,
X * shifted back to normal ASCII, and then offset from ASCII space
X * (ie. aa_c[0] - ' ').
X *
X * The sid has values ASCII '0' -> ASCII '0'+15. ASCII '0' is subtraced and
X * the low 4 bits of the ether_addr are set from that.
X */
X
X/* screw digipeaters */
Xstruct ax25_hdr {
X u_char ah_dst[7], ah_src[7];
X u_char ah_cmd;
X u_char ah_pid;
X};
X
X/*
X * AX25 commands. All others are tossed.
X */
X#define AX25CMD_UI 0x03 /* AX25 datagram */
X
X/*
X * AX25 Protocol IDs. All others are tossed.
X */
X#define AX25PID_IP 0xcc /* ARPA IP */
X#define AX25PID_ARP 0xcd /* ARPA ARP */
X
X/*
X * AX25 ARP address types.
X */
X#define AX25_HARDTYPE 0x0003
X#define AX25_IPTYPE ((short)AX25PID_IP)
X
X/*
X * KISS framing. This is SLIP.
X */
X#define KISS_END 0xc0
X#define KISS_ESC 0xdb
X#define KISS_TEND 0xdc
X#define KISS_TESC 0xdd
X
X/*
X * KISS commands - first data byte inside the KISS packet.
X */
X#define KISS_DATA 0x00
X#define KISS_TXDELAY 0x01
X#define KISS_PERSISTANCE 0x02
X#define KISS_SLOTTIME 0x03
X#define KISS_TXTAIL 0x04
X#define KISS_FULLDUPLEX 0x05
X#define KISS_HARDWARE 0x06
X#define KISS_QUIT 0xff
X
X#endif /* _if_ax_h_ */
END_OF_FILE
if test 1890 -ne `wc -c <'if_ax.h'`; then
echo shar: \"'if_ax.h'\" unpacked with wrong size!
fi
# end of 'if_ax.h'
fi
if test -f 'tty_ax.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tty_ax.c'\"
else
echo shar: Extracting \"'tty_ax.c'\" \(23598 characters\)
sed "s/^X//" >'tty_ax.c' <<'END_OF_FILE'
X/*
X * KISS+AX25 IP streams module for sunos 4.x
X *
X * Copyright 1991, 1992 by Theo de Raadt
X *
X * Theo de Raadt <deraadt@lego.cuc.ab.ca>
X * Thanks to William Graham <uug@indigo.cuc.ab.ca> for AX25 specs.
X *
X * Streams ideas ripped off from PPP and SLIP implimentations for
X * Sunos by Brad Clements and Rayan Zachariassen respectively.
X */
X#undef DEBUG
X#undef DEBUG2
X#define AX_NIT
X
X#include "ax.h"
X#if NAX > 0
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stream.h>
X#include <sys/stropts.h>
X#include <sys/dir.h>
X#include <sys/signal.h>
X#include <sys/user.h>
X#include <sys/mbuf.h>
X#include <sys/socket.h>
X#include <sys/sockio.h>
X#include <sys/syslog.h>
X
X#include <netinet/in.h>
X
X#include <net/if.h>
X#include <net/nit_if.h>
X#include <netinet/if_ether.h>
X#include <sys/if_ax.h>
X
X#include <net/netisr.h>
X
X#include <netinet/in_systm.h>
X#include <netinet/in_var.h>
X#include <netinet/ip.h>
X
X#ifdef AX_NIT
Xstatic struct ether_header nitheader = { {{1}}, {{2}}, ETHERTYPE_IP };
Xstatic struct nit_if nif = {(caddr_t)&nitheader, sizeof(nitheader), 0, 0};
X
Xstatic struct ether_header nitheader_arp = { {{1}}, {{2}}, ETHERTYPE_ARP };
Xstatic struct nit_if nif_arp = {(caddr_t)&nitheader_arp, sizeof(nitheader_arp), 0, 0};
X#endif
X
Xint ax_attach();
Xstatic int ax_open(), ax_close(), ax_rput(), ax_wput(), ax_wsrv();
Xstatic int ax_ioctl(), ax_output();
Xstatic struct mbuf *ax_btom();
X
Xstatic struct module_info minfo = {
X 0xabce, AXSTREAMNAME, 0, INFPSZ, 16384, 4096
X};
X
Xstatic struct qinit r_init = {
X ax_rput, NULL, ax_open, ax_close, NULL, &minfo, NULL
X};
X
Xstatic struct qinit w_init = {
X ax_wput, ax_wsrv, ax_open, ax_close, NULL, &minfo, NULL
X};
X
Xstruct streamtab axinfo = {
X &r_init, &w_init, NULL, NULL, NULL
X};
X
Xstatic struct axpriv {
X struct arpcom arpcom;
X queue_t *q;
X u_char *buf;
X u_char *dp;
X u_int inlen;
X u_char gotesc, toobig;
X} axpriv[NAX];
X
Xstatic u_char ax25broadcastaddr[7] = {
X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1
X};
Xstatic struct ether_addr ethernulladdr;
X
Xint
Xax_attach(unit)
Xint unit;
X{
X register struct ifnet *ifp = &axpriv[unit].arpcom.ac_if;
X
X ifp->if_name = AXIFNAME;
X ifp->if_mtu = AX25MTU;
X ifp->if_flags = IFF_BROADCAST;
X ifp->if_unit = unit;
X ifp->if_ioctl = ax_ioctl;
X ifp->if_output = ax_output;
X ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
X if_attach(ifp);
X return 0;
X}
X
Xstatic int
Xax_open(q, dev, flag, sflag)
Xqueue_t *q;
Xdev_t dev;
Xint flag, sflag;
X{
X struct axpriv *axp;
X int unit, s;
X
X if( !suser()) {
X u.u_error = EPERM;
X return OPENFAIL;
X }
X
X s = splstr();
X for( unit=0; unit<NAX; ++unit) {
X axp = &axpriv[unit];
X
X if(axp->buf)
X continue;
X if(axp->arpcom.ac_if.if_mtu == 0)
X ax_attach(unit);
X axp->arpcom.ac_if.if_flags |= IFF_RUNNING;
X axp->buf = (u_char *)kmem_alloc(AX25MTU);
X axp->dp = axp->buf + sizeof(struct ifnet *);
X axp->inlen = 0;
X axp->q = WR(q);
X WR(q)->q_ptr = q->q_ptr = (caddr_t)axp;
X (void) splx(s);
X log(LOG_INFO, "ax%d: coming up\n", unit);
X return unit;
X }
X splx(s);
X log(LOG_INFO, "ax%d: no more devices available\n", NAX);
X return OPENFAIL;
X}
X
Xstatic int
Xax_close(q, flag)
Xqueue_t *q;
Xint flag;
X{
X struct axpriv *axp;
X int s;
X
X s = splimp();
X axp = (struct axpriv *)q->q_ptr;
X if(axp) {
X log(LOG_INFO, "ax%d: going down\n", axp->arpcom.ac_if.if_unit);
X if_down(&axp->arpcom.ac_if);
X axp->arpcom.ac_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
X if(axp->buf)
X kmem_free(axp->buf, AX25MTU);
X axp->buf = NULL;
X axp->q = NULL;
X }
X (void) splx(s);
X}
X
Xstatic int
Xax_wput(q, mp)
Xqueue_t *q;
Xmblk_t *mp;
X{
X struct axpriv *axp;
X char ax25[7];
X struct iocblk *iocp;
X
X switch(mp->b_datap->db_type) {
X case M_FLUSH:
X if(*mp->b_rptr & FLUSHW)
X flushq(q, FLUSHDATA);
X putnext(q, mp);
X break;
X case M_DATA:
X putq(q, mp);
X break;
X case M_IOCTL:
X iocp = (struct iocblk *)mp->b_rptr;
X axp = (struct axpriv *)q->q_ptr;
X switch(iocp->ioc_cmd) {
X case AXIOSHADDR:
X bcopy((caddr_t)mp->b_cont->b_rptr,
X (caddr_t)&axp->arpcom.ac_enaddr,
X sizeof(struct ether_addr));
X mp->b_datap->db_type = M_IOCACK;
X iocp->ioc_rval = iocp->ioc_count = iocp->ioc_error = 0;
X qreply(q, mp);
X log(LOG_INFO, "ax%d: ether %2x:%2x:%2x:%2x:%2x:%2x ax25 ",
X axp->arpcom.ac_if.if_unit,
X axp->arpcom.ac_enaddr.ether_addr_octet[0],
X axp->arpcom.ac_enaddr.ether_addr_octet[1],
X axp->arpcom.ac_enaddr.ether_addr_octet[2],
X axp->arpcom.ac_enaddr.ether_addr_octet[3],
X axp->arpcom.ac_enaddr.ether_addr_octet[4],
X axp->arpcom.ac_enaddr.ether_addr_octet[5]);
X ax_ether2ax(&axp->arpcom.ac_enaddr, ax25);
X print_ax25addr(ax25);
X printf("\n");
X return;
X case AXIOGUNIT:
X iocp->ioc_rval = 0;
X if( mp->b_cont = allocb(sizeof(int), BPRI_MED) ) {
X u_char *cp = mp->b_cont->b_wptr;
X
X mp->b_datap->db_type = M_IOCACK;
X *((int *)cp) = axp->arpcom.ac_if.if_unit;
X mp->b_cont->b_wptr += sizeof(int);
X iocp->ioc_count = sizeof(int);
X iocp->ioc_error = 0;
X qreply(q, mp);
X break;
X }
X iocp->ioc_error = ENOSR;
X mp->b_datap->db_type = M_IOCNAK;
X qreply(q, mp);
X return;
X default:
X log(LOG_INFO, "ax%d: unknown ioc %8x\n",
X axp->arpcom.ac_if.if_unit, iocp->ioc_cmd);
X putnext(q, mp);
X return;
X }
X break;
X default:
X putnext(q, mp);
X }
X}
X
Xstatic int
Xax_rput(q, mp)
Xqueue_t *q;
Xmblk_t *mp;
X{
X struct axpriv *axp = (struct axpriv *)q->q_ptr;
X struct ifnet *ifp;
X register u_char c, *rp;
X register mblk_t *bp;
X struct mbuf *m;
X int proto, forus, s;
X
X if( axp==NULL ) {
X log(LOG_INFO, "ax_rput: axp is NULL\n");
X freemsg(mp);
X return;
X }
X if( axp->buf==NULL ) {
X log(LOG_INFO, "ax_rput: axp->buf is NULL\n");
X freemsg(mp);
X return;
X }
X
X ifp = &axp->arpcom.ac_if;
X switch(mp->b_datap->db_type) {
X case M_DATA:
X break;
X case M_FLUSH:
X if(*mp->b_rptr & FLUSHR)
X flushq(q, FLUSHDATA);
X putnext(q, mp);
X return;
X case M_UNHANGUP:
X log(LOG_INFO, "ax%d: M_UNHANGUP\n", ifp->if_unit);
X axp->q = WR(q); /* hook us up again */
X putnext(q, mp);
X putctl1(q->q_next, M_PCSIG, SIGURG);
X return;
X case M_HANGUP:
X log(LOG_INFO, "ax%d: M_HANGUP\n", ifp->if_unit);
X s = splstr();
X axp->q = NULL; /* cause ax_output to return ENETDOWN */
X (void) splx(s);
X putnext(q, mp);
X return;
X case M_BREAK:
X case M_IOCACK:
X putnext(q, mp);
X return;
X default:
X log(LOG_INFO, "ax%d: rput streams message type %d discarded\n",
X ifp->if_unit, mp->b_datap->db_type);
X putnext(q, mp);
X return;
X }
X
X /*
X * Perform the KISS protocol on the streams message, and add the bytes
X * to a packet reconstruction buffer. When a complete AX25 packet has
X * been collected, strip the AX25 layer and provide the IP (or ARP) packet
X * inside to the networking code.
X */
X for( bp=mp; bp; bp=bp->b_cont) {
X rp = bp->b_rptr;
X while( rp < bp->b_wptr) {
X c = *rp++;
X /*printf("K %2x\n", c);*/
X if(axp->gotesc) {
X axp->gotesc = 0;
X if(c==KISS_TEND)
X c = KISS_END;
X else if(c==KISS_TESC)
X c = KISS_ESC;
X#ifdef DEBUG
X else
X log(LOG_INFO, "ax%d: kiss ESC error (c=%d)\n",
X ifp->if_unit, c);
X#endif
X } else if(c==KISS_END) {
X if(axp->toobig) {
X axp->toobig = 0;
X /*printf("ax%d: packet toobig\n",
X ifp->if_unit);*/
X axp->inlen = 0;
X continue;
X }
X if(axp->inlen==0)
X continue;
X
X /*
X * buf contains KISS_DATA followed by an AX25
X * packet. Extract the IP packet lurking inside
X * AX25 packet..
X */
X m = ax_btom(axp, &proto, &forus);
X axp->dp = axp->buf + sizeof(struct ifnet *);
X ifp->if_ipackets++;
X axp->inlen = 0;
X if(!m) {
X ifp->if_ierrors++;
X continue;
X }
X
X switch(proto) {
X case AX25PID_IP:
X#ifdef AX_NIT
X if(ifp->if_flags & IFF_PROMISC) {
X struct mbuf *nm = m;
X int len = 0;
X
X do {
X len += nm->m_len;
X } while( nm=nm->m_next );
X len -= sizeof(struct ifnet *);
X m->m_off += sizeof(struct ifnet *);
X nif.nif_bodylen = len;
X snit_intr(&axp->arpcom, m, &nif);
X m->m_off -= sizeof(struct ifnet *);
X }
X#endif
X if(!forus) {
X m_freem(m);
X break;
X }
X s = splimp();
X if( IF_QFULL(&ipintrq) ) {
X IF_DROP(&ipintrq);
X ifp->if_ierrors++;
X m_freem(m);
X (void) splx(s);
X } else {
X IF_ENQUEUE(&ipintrq, m);
X schednetisr(NETISR_IP);
X (void) splx(s);
X#ifdef DEBUG
X log(LOG_INFO, "handing off to IP\n");
X#endif
X }
X break;
X case AX25PID_ARP:
X#ifdef AX_NIT
X if(ifp->if_flags & IFF_PROMISC) {
X struct mbuf *nm = m;
X int len = 0;
X
X do {
X len += nm->m_len;
X } while( nm=nm->m_next );
X len -= sizeof(struct ifnet *);
X m->m_off += sizeof(struct ifnet *);
X nif_arp.nif_bodylen = len;
X snit_intr(&axp->arpcom, m, &nif_arp);
X m->m_off -= sizeof(struct ifnet *);
X }
X#endif
X if(!forus) {
X m_freem(m);
X break;
X }
X#ifdef DEBUG
X printf("[INCOMING ethernet arp packet]");
X ax25_arpdebug(m);
X#endif
X arpinput(&axp->arpcom, m);
X break;
X default:
X#ifdef DEBUG2
X printf("ax%d: unknown protocol %d\n",
X ifp->if_unit,
X proto);
X#endif
X m_freem(m);
X break;
X }
X continue;
X } else if(c==KISS_ESC) {
X axp->gotesc = 1;
X continue;
X }
X if(++axp->inlen > AX25MTU) {
X if(axp->toobig)
X continue;
X axp->toobig = 1;
X ifp->if_ierrors++;
X axp->dp = axp->buf + sizeof(struct ifnet *);
X continue;
X } else
X *axp->dp++ = c;
X }
X bp->b_rptr = rp;
X }
X freemsg(mp);
X return;
X}
X
X
Xstatic struct mbuf *
Xax_btom(axp, protop, forusp)
Xstruct axpriv *axp;
Xint *protop, *forusp;
X{
X struct ax25_hdr *ax;
X struct mbuf *m, **mp, *top = NULL;
X struct ifnet *ifp;
X struct ether_addr oureth;
X int len, count;
X caddr_t cp;
X
X ax = (struct ax25_hdr *)(axp->buf + sizeof(struct ifnet *) + 1);
X
X /*
X * digipeaters are not supported (they could be supported - could
X * correct the AX25 packet's fields, KISS encode it, and send a
X * message downstream to the TNC.)
X *
X * The IP packet must come in an AX25 UI frame.
X */
X if(ax->ah_cmd != AX25CMD_UI) {
X#ifdef DEBUG2
X printf("ax%d: ax25 frame not UI, cmd=%2x\n",
X axp->arpcom.ac_if.if_unit, ax->ah_cmd);
X#endif
X return NULL;
X }
X
X#ifdef DEBUG2
X printf("ax%d: ", axp->arpcom.ac_if.if_unit);
X print_ax25addr(ax->ah_src);
X printf("->");
X print_ax25addr(ax->ah_dst);
X printf(" [%d]\n", axp->inlen - sizeof(struct ax25_hdr) - 1);
X#endif
X
X /*
X * is this packet to us?
X */
X *forusp = 1;
X ax_ax2ether(ax->ah_dst, &oureth);
X if( bcmp((caddr_t)&oureth, (caddr_t)&axp->arpcom.ac_enaddr,
X sizeof oureth) &&
X bcmp((caddr_t)ax25broadcastaddr, (caddr_t)&axp->arpcom.ac_enaddr,
X sizeof oureth)) {
X *forusp = 0;
X }
X
X /*
X * packet not for us, and not promisc mode --> can out.
X */
X if( !(axp->arpcom.ac_if.if_flags & IFF_PROMISC) && *forusp==0)
X return NULL;
X
X /*
X * check acceptable protocols
X */
X switch(ax->ah_pid) {
X case AX25PID_IP:
X case AX25PID_ARP:
X break;
X default:
X#ifdef DEBUG2
X printf("ax%d: packet discarded - protocol %d\n",
X axp->arpcom.ac_if.if_unit, ax->ah_pid);
X#endif
X return NULL;
X }
X
X *protop = (int)(ax->ah_pid);
X ifp = &axp->arpcom.ac_if;
X cp = (caddr_t)(axp->buf + sizeof(struct ifnet *) + 1 + sizeof(struct ax25_hdr));
X mp = ⊤
X len = axp->inlen - 1 - sizeof(struct ax25_hdr);
X while(len>0) {
X MGET(m, M_DONTWAIT, MT_DATA);
X if(m == NULL) {
X if(top)
X m_freem(top);
X return NULL;
X }
X *mp = m;
X if(ifp) {
X m->m_off += sizeof(ifp);
X count = MIN(len, MLEN - sizeof(ifp));
X bcopy(cp, mtod(m, caddr_t), count);
X m->m_len = count;
X m->m_off -= sizeof(ifp);
X m->m_len += sizeof(ifp);
X *mtod(m, struct ifnet **) = ifp;
X ifp = NULL;
X } else {
X count = MIN(len, MLEN);
X bcopy(cp, mtod(m, caddr_t), count);
X m->m_len = count;
X }
X cp += count;
X len -= count;
X mp = &m->m_next;
X }
X if(ax->ah_pid== AX25PID_ARP) {
X top->m_off += sizeof(ifp); /* XXX ax_ax2etherarp() weak */
X ax_ax2etherarp(top);
X top->m_off -= sizeof(ifp);
X }
X
X return top;
X}
X
X
Xstatic int
Xax_wsrv(q)
Xqueue_t *q;
X{
X register mblk_t *mp;
X
X while( mp=getq(q) ) {
X if( !canput(q->q_next)) {
X putbq(q, mp);
X return;
X }
X putnext(q, mp);
X }
X}
X
X/* %%% ifconfig ether #:#:#:#:#:# not working */
Xstatic int
Xax_ioctl(ifp, cmd, data)
Xstruct ifnet *ifp;
Xint cmd;
Xcaddr_t data;
X{
X register struct ifaddr *ifa = (struct ifaddr *)data;
X register struct ifreq *ifr = (struct ifreq *)data;
X int error = 0, s;
X
X if(ifa==NULL)
X return EFAULT;
X s = splimp();
X switch(cmd) {
X case SIOCSIFFLAGS:
X if(!data) /* IFF_PROMISC change */
X break;
X if(!suser()) {
X error = EPERM;
X break;
X }
X ifp->if_flags &= IFF_CANTCHANGE;
X ifp->if_flags |= (ifr->ifr_flags & ~IFF_CANTCHANGE);
X break;
X case SIOCGIFFLAGS:
X ifr->ifr_flags = ifp->if_flags;
X break;
X case SIOCSIFADDR:
X switch(ifa->ifa_addr.sa_family) {
X case AF_INET:
X ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
X ifp->if_flags |= IFF_UP;
X break;
X default:
X error = EAFNOSUPPORT;
X break;
X }
X break;
X case SIOCSIFBRDADDR:
X if(ifa->ifa_addr.sa_family != AF_INET)
X error = EAFNOSUPPORT;
X break;
X case SIOCSIFNETMASK:
X if(ifa->ifa_addr.sa_family != AF_INET)
X error = EAFNOSUPPORT;
X break;
X default:
X error = EINVAL;
X }
X (void) splx(s);
X return error;
X}
X
Xstatic int
Xax_output(ifp, m0, dst)
Xstruct ifnet *ifp;
Xstruct mbuf *m0;
Xstruct sockaddr *dst;
X{
X struct axpriv *axp;
X struct ax25_hdr ax25;
X struct ether_header *eth;
X struct mbuf *m = m0;
X int i, len, s, n;
X struct in_addr idst;
X u_char *cp, *cp2;
X mblk_t *mp;
X
X axp = &axpriv[ifp->if_unit];
X if(axp->q == NULL)
X return ENETDOWN;
X
X /* printf("ax%d: trying to send packet\n", ifp->if_unit); */
X
X switch(dst->sa_family) {
X case AF_INET:
X#ifdef AX_NIT
X if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) {
X struct mbuf *nm = m0;
X int len = 0;
X
X do {
X len += nm->m_len;
X } while( nm=nm->m_next );
X nif.nif_bodylen = len;
X snit_intr(&axp->arpcom, m0, &nif);
X }
X
X#endif
X idst = ((struct sockaddr_in *)dst)->sin_addr;
X ((struct arpcom *)ifp)->ac_lastip = idst;
X m = m0;
X if( !arpresolve((struct arpcom *)ifp, m)) {
X return 0;
X }
X#ifdef DEBUG2
X len = 0;
X for(m=m0; m; m=m->m_next) {
X cp = mtod(m, u_char *);
X n = m->m_len;
X while(n-->0) {
X if( !(len++ % 16) )
X printf("\n\t");
X printf("%2x ", *cp++);
X }
X }
X if( len % 16 )
X printf("\n");
X#endif
X ax25.ah_pid = AX25PID_IP;
X ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src);
X ax_ether2ax(&((struct arpcom *)ifp)->ac_lastarp, ax25.ah_dst);
X#ifdef DEBUG2
X printf("ax%d: sending to ", ifp->if_unit);
X print_ax25addr(ax25.ah_dst);
X printf("\n");
X#endif
X break;
X case AF_UNSPEC:
X eth = (struct ether_header *)dst->sa_data;
X switch(eth->ether_type) {
X case ETHERTYPE_ARP:
X case ETHERTYPE_REVARP:
X#ifdef AX_NIT
X if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) {
X struct mbuf *nm = m0;
X int len = 0;
X
X do {
X len += nm->m_len;
X } while( nm=nm->m_next );
X nif_arp.nif_bodylen = len;
X snit_intr(&axp->arpcom, m0, &nif_arp);
X }
X
X#endif
X#ifdef DEBUG2
X printf("AF_UNSPEC: ARP\n");
X printf("[ethernet arp packet]");
X len = 0;
X for(m=m0; m; m=m->m_next) {
X cp = mtod(m, u_char *);
X n = m->m_len;
X while(n-->0) {
X if( !(len++ % 16) )
X printf("\n\t");
X printf("%2x ", *cp++);
X }
X }
X if( len % 16 )
X printf("\n");
X#endif
X
X ax_ether2axarp(m0);
X ax25.ah_pid = AX25PID_ARP;
X ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src);
X ax_ether2ax(ð->ether_dhost, ax25.ah_dst);
X#ifdef DEBUG2
X printf("[AX25 arp packet]");
X#endif
X break;
X default:
X printf("AF_UNSPEC: unknown ether_type %4x",
X ntohs(eth->ether_type));
X ax25.ah_pid = AX25PID_IP; /* wrong */
X ax_ether2ax(ð->ether_shost, ax25.ah_src);
X ax_ether2ax(ð->ether_dhost, ax25.ah_dst);
X break;
X }
X
X#ifdef DEBUG2
X len = 0;
X for(m=m0; m; m=m->m_next) {
X cp = mtod(m, u_char *);
X n = m->m_len;
X while(n-->0) {
X if( !(len++ % 16) )
X printf("\n\t");
X printf("%2x ", *cp++);
X }
X }
X if( len % 16 )
X printf("\n");
X#endif
X
X break;
X default:
X log(LOG_INFO, "ax%d: cannot handle af%d\n", ifp->if_unit,
X dst->sa_family);
X m_freem(m0);
X return EAFNOSUPPORT;
X }
X
X ax25.ah_cmd = AX25CMD_UI;
X ax25.ah_src[6] |= 0x01; /* %%% set low bit on src */
X
X /*
X * run through the ax25_hdr and the packet buffer counting
X * how much space we need for KISS encoding.
X */
X len = 2; /* KISS_END, KISS_DATA */
X for(i=0, cp=(u_char *)&ax25; i< sizeof(ax25); i++, cp++) {
X len++;
X if(*cp==KISS_END || *cp==KISS_ESC)
X len++;
X }
X for(m=m0; m; m=m->m_next) {
X cp = mtod(m, u_char *);
X for(i=0; i< m->m_len; i++, cp++) {
X len++;
X if(*cp==KISS_END || *cp==KISS_ESC)
X len++;
X }
X }
X len++; /* KISS_END */
X
X if( !(mp = allocb(len, BPRI_MED)) ) {
X log(LOG_INFO, "ax%d: ax_output cannot allocb %d bytes\n",
X ifp->if_unit, len);
X m_freem(m0);
X return ENOSR;
X }
X
X#ifdef DEBUG2
X cp2 = mp->b_wptr;
X#endif
X
X /*
X * KISS-format the ax25 header and data into mp.
X */
X *mp->b_wptr++ = KISS_END;
X *mp->b_wptr++ = KISS_DATA;
X for(i=0, cp=(u_char *)&ax25; i<sizeof(ax25); i++, cp++) {
X switch(*cp) {
X case KISS_END:
X *mp->b_wptr++ = KISS_ESC;
X *mp->b_wptr++ = KISS_TEND;
X break;
X case KISS_ESC:
X *mp->b_wptr++ = KISS_ESC;
X *mp->b_wptr++ = KISS_TESC;
X break;
X default:
X *mp->b_wptr++ = *cp;
X break;
X }
X }
X for(m=m0; m; m=m->m_next) {
X cp = mtod(m, u_char *);
X for(i=0; i< m->m_len; i++, cp++) {
X switch(*cp) {
X case KISS_END:
X *mp->b_wptr++ = KISS_ESC;
X *mp->b_wptr++ = KISS_TEND;
X break;
X case KISS_ESC:
X *mp->b_wptr++ = KISS_ESC;
X *mp->b_wptr++ = KISS_TESC;
X break;
X default:
X *mp->b_wptr++ = *cp;
X break;
X }
X }
X }
X *mp->b_wptr++ = KISS_END; /* superfluous, really */
X
X#ifdef DEBUG2
X printf("actual serial output:\n");
X while(cp2 < mp->b_wptr)
X printf("%2x ", *cp2++);
X printf("\n");
X#endif
X
X s = splstr();
X if(axp->q)
X putq(axp->q, mp);
X else
X freemsg(mp);
X (void) splx(s);
X m_freem(m0);
X return 0;
X}
X
X/*
X * convert an ethernet ARP packet to an AX25 ARP packet. The AX25 frame
X * header is not included.
X */
Xax_ether2axarp(m)
Xstruct mbuf *m;
X{
X struct arphdr *arp = mtod(m, struct arphdr *);
X struct ether_addr eth1, eth2;
X struct in_addr in1, in2;
X caddr_t cp;
X
X arp->ar_hrd = AX25_HARDTYPE;
X arp->ar_pro = AX25_IPTYPE;
X arp->ar_hln = 7;
X
X cp = ((caddr_t)arp) + sizeof(struct arphdr);
X bcopy(cp, (caddr_t)ð1, sizeof(struct ether_addr));
X cp += sizeof(struct ether_addr);
X bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr));
X cp += sizeof(struct in_addr);
X bcopy(cp, (caddr_t)ð2, sizeof(struct ether_addr));
X cp += sizeof(struct ether_addr);
X bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr));
X
X cp = ((caddr_t)arp) + sizeof(struct arphdr);
X ax_ether2ax(ð1, (u_char *)cp);
X cp += 7;
X bcopy((caddr_t)&in1, cp, sizeof(struct in_addr));
X cp += sizeof(struct in_addr);
X ax_ether2ax(ð2, (u_char *)cp);
X cp += 7;
X bcopy((caddr_t)&in2, cp, sizeof(struct in_addr));
X
X m->m_len += 2;
X return 0;
X}
X
X/*
X * convert an AX25 ARP packet to an ethernet ARP packet. The AX25 frame
X * is assumed to have been already stripped off.
X */
Xax_ax2etherarp(m)
Xstruct mbuf *m;
X{
X struct arphdr *arp = mtod(m, struct arphdr *);
X u_char axa1[7], axa2[7];
X struct in_addr in1, in2;
X caddr_t cp;
X
X#ifdef DEBUG2
X printf("[INCOMING AX25 arp packet]");
X ax25_arpdebug(m);
X#endif
X
X arp->ar_hrd = ARPHRD_ETHER;
X arp->ar_pro = ETHERTYPE_IP;
X arp->ar_hln = sizeof(struct ether_addr);
X
X cp = ((caddr_t)arp) + sizeof(struct arphdr);
X bcopy(cp, (caddr_t)axa1, 7);
X cp += 7;
X bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr));
X cp += sizeof(struct in_addr);
X bcopy(cp, (caddr_t)axa2, 7);
X cp += 7;
X bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr));
X
X cp = ((caddr_t)arp) + sizeof(struct arphdr);
X ax_ax2ether(axa1, (struct ether_addr *)cp);
X cp += sizeof(struct ether_addr);
X bcopy((caddr_t)&in1, cp, sizeof(struct in_addr));
X cp += sizeof(struct in_addr);
X ax_ax2ether(axa2, (struct ether_addr *)cp);
X cp += sizeof(struct ether_addr);
X bcopy((caddr_t)&in2, cp, sizeof(struct in_addr));
X
X m->m_len -= 2;
X return 0;
X}
X
X/*
X * convert an ax25_addr to an ether_addr
X */
Xax_ax2ether(axhp, ethp)
Xu_char *axhp;
Xstruct ether_addr *ethp;
X{
X u_char c;
X int i;
X
X#ifdef DEBUG2
X for(i=0; i<6; i++)
X printf("%2x.", axhp[i]);
X printf("%2x '", axhp[6]);
X
X for(i=0; i<(7-1); i++)
X printf("%c", (axhp[i]>>1) & 0x7f );
X printf("-%c' == ", (axhp[6]&0x7f)>>1 & 0x7f );
X#endif
X
X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr,
X sizeof(ax25broadcastaddr)) ) {
X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp,
X sizeof(struct ether_addr));
X goto done;
X }
X
X ethp->ether_addr_octet[0] = 0x99;
X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[1] = c;
X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0);
X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f);
X ethp->ether_addr_octet[2] = c;
X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0);
X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f);
X ethp->ether_addr_octet[3] = c;
X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc);
X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03);
X ethp->ether_addr_octet[4] = c;
X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0);
X c |= (((((axhp[6]&0x7f)>>1) - '0') ) & 0x0f);
X ethp->ether_addr_octet[5] = c;
X
Xdone:
X#ifdef DEBUG2
X for(i=0; i<sizeof(struct ether_addr)-1; i++)
X printf("%2x:", ethp->ether_addr_octet[i]);
X printf("%2x\n", ethp->ether_addr_octet[5]);
X#endif
X return 0;
X}
X
X/*
X * convert an ether_addr to an ax25_addr
X */
Xax_ether2ax(ethp, axhp)
Xstruct ether_addr *ethp;
Xu_char *axhp;
X{
X u_char c;
X int i;
X
X#ifdef DEBUG2
X for(i=0; i<sizeof(struct ether_addr)-1; i++)
X printf("%2x:", ethp->ether_addr_octet[i]);
X printf("%2x == ", ethp->ether_addr_octet[5]);
X#endif
X
X if( !bcmp((caddr_t)ethp, (caddr_t)ðernulladdr,
X sizeof(struct ether_addr))) {
X#ifdef DEBUG2
X printf("nothing\n");
X#endif
X for(i=0; i<7; i++)
X axhp[i] = (u_char)0;
X return;
X }
X if( !bcmp((caddr_t)ethp, (caddr_t)ðerbroadcastaddr,
X sizeof(struct ether_addr))) {
X bcopy((caddr_t)ax25broadcastaddr, (caddr_t)axhp,
X sizeof(ax25broadcastaddr));
X goto done;
X }
X c = ethp->ether_addr_octet[0];
X if(c != 0x99) {
X#ifdef DEBUG2
X printf("[NO MAPPING]\n");
X#endif
X for(i=0; i<7; i++)
X axhp[i] = (u_char)0;
X return;
X }
X c = (ethp->ether_addr_octet[1] >> 2) & 0x3f;
X axhp[0] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[1] << 4) & 0x30;
X c |= (ethp->ether_addr_octet[2] >> 4) & 0x0f;
X axhp[1] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[2] << 2) & 0x3c;
X c |= (ethp->ether_addr_octet[3] >> 6) & 0x03;
X axhp[2] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[3] ) & 0x3f;
X axhp[3] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[4] >> 2) & 0x3f;
X axhp[4] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[4] << 4) & 0x30;
X c |= (ethp->ether_addr_octet[5] >> 4) & 0x0f;
X axhp[5] = (u_char)((c + ' ') << 1);
X c = (ethp->ether_addr_octet[5] ) & 0x0f;
X axhp[6] = (u_char)((c + '0') << 1);
X
Xdone:
X#ifdef DEBUG2
X for(i=0; i<6; i++)
X printf("%2x.", axhp[i]);
X printf("%2x '", axhp[6]);
X
X for(i=0; i<6; i++)
X printf("%c", (axhp[i] >> 1) & 0x7f );
X printf("-%c'\n", ((axhp[6] & 0x7f) >> 1) & 0x7f );
X#endif
X return;
X}
X
Xprint_ax25addr(axhp)
Xu_char *axhp;
X{
X int i;
X
X#ifdef DEBUG2
X for(i=0; i<6; i++)
X printf("%2x.", axhp[i]);
X printf("%2x", axhp[6]);
X#endif
X
X printf("(");
X for(i=0; i<6; i++)
X printf("%c", (axhp[i]>>1) & 0x7f );
X printf("-%c)", ((axhp[6]&0x7f)>>1) & 0x7f );
X}
X
Xax25_arpdebug(m0)
Xstruct mbuf *m0;
X{
X struct mbuf *m;
X int len, n;
X u_char *cp;
X
X len = 0;
X for(m=m0; m; m=m->m_next) {
X printf("*");
X cp = mtod(m, u_char *);
X n = m->m_len;
X while(n-->0) {
X if( !(len++ % 16) )
X printf("\n\t");
X printf("%2x ", *cp++);
X }
X }
X if( len % 16 )
X printf("\n");
X}
X
X
X#endif /* !(NAX > 0) */
X
END_OF_FILE
if test 23598 -ne `wc -c <'tty_ax.c'`; then
echo shar: \"'tty_ax.c'\" unpacked with wrong size!
fi
# end of 'tty_ax.c'
fi
echo shar: End of shell archive.
exit 0